use std::fs::File;
use jizi_fs::Xdg ;
use jizi_shared::{RoCell, LOG_LEVEL};
use anyhow::Context;
use crossterm::style::{Color, Print, ResetColor, SetForegroundColor};
use tracing_appender::non_blocking::WorkerGuard ;
use tracing_subscriber::EnvFilter ; 
pub (super) struct  Logs ;

static _GUARD : RoCell<WorkerGuard> = RoCell::new() ;

impl Logs {
    pub(super) fn start() -> anyhow::Result<()> {
        let level = LOG_LEVEL.get() ; // LOG_LEVEL是一个被Sync包裹的枚举类
        
        if level.is_none() {  // 不使用Log
            return Ok(()) ;
        }
        
        let state_dir = Xdg::state_dir() ; // 获取状态目录
        std::fs::create_dir_all(&state_dir) // 创建状态目录
            .with_context(|| format!("failed to create state directory:{state_dir:?}")) ? ;
        
        let log_path = state_dir.join("jizi.log") ;
        let log_file = File::create(&log_path)
            .with_context(|| format!("failed to create log file:{log_path:?}"))?;  // 在状态目录下创建log文件
        
        // tracing-appender::non_blocking 是一个非阻塞的日志写入器，将写日志操作异步化避免阻塞主线程
        let (non_blocking , guard) = tracing_appender::non_blocking(log_file) ;
        // 配置日志订阅器 
        tracing_subscriber::fmt()  // 创建格式化的日志订阅器
            .pretty() // 美观模式
            .with_env_filter(EnvFilter::new(level)) 
            .with_writer(non_blocking)
            .with_ansi(cfg!(debug_assertions))
            .init() ; // 初始化全局日志订阅器
        
        _GUARD.init(guard) ;   // 初始化_guard  存入guard
        // workerguard 是tracing appender的守护对象， 作用是保证日志缓冲区的内容在程序结束前被完全刷盘
        // 如果不存储guard 那么guard会在作用域结束时被丢弃  导致部分日志的丢失
        Ok(crossterm::execute!(
            std::io::stderr() , 
            SetForegroundColor(Color::Yellow) ,
            Print(format!("Running with log level `{level}`, logs are written to {log_path:?}\n")) ,
            ResetColor 
        )?) 
        // 上面代码有个等价写法
        // match crossterm::execute!(
        //     std::io::stderr() , 
        //     SetForegroundColor(Color::Yellow) , 
        //     Print(format!("Running with log level `{level}`, logs are written to {log_path:?}\n")) ,
        //     ResetColor 
        // ) {
        //     Ok(_) => Ok(()) ,
        //     Err(e) => Err(anyhow::Error::new(e)) , 
        // }
    }
}